home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 2.iso / toolbox / public / figlet / figlet2.1.1 / chkfont.c next >
C/C++ Source or Header  |  1996-11-11  |  11KB  |  405 lines

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <ctype.h>
  4.  
  5. #define DATE "25 Aug 1994"
  6. #define VERSION "2.1.1"
  7.  
  8. /*
  9.    chkfont
  10.    By Glenn Chappell <ggc@uiuc.edu>
  11.  
  12.    This program checks figlet 2.0/2.1 font files for format errors.
  13.    It also looks for signs of common problems and gives warnings.
  14.    chkfont does not modify font files.
  15.  
  16.    Usage: chkfont fontfile ...
  17.  
  18.    Note: This is very much a spare-time project. It's probably
  19.    full o' bugs ....
  20. */
  21.  
  22. /* #define CHECKBLANKS */
  23. #define FONTFILESUFFIX ".flf"
  24. #define FONTFILEMAGICNUMBER "flf2"
  25. char posshardblanks[9] = { '!', '@', '#', '$', '%', '&', '*', 0x7f, 0 };
  26.  
  27. char *myname,*fontfilename;
  28. FILE *fontfile;
  29. char hardblank;
  30. int charheight,upheight,maxlen=0,smushmode;
  31. char *fileline;
  32. int maxlinelength=0,currline;
  33. int ec,wc;
  34.  
  35. int incon_endmarkwarn,endmark_countwarn,nonincrwarn;
  36. int bigcodetagwarn,smallcodetagwarn,deutschcodetagwarn,asciicodetagwarn;
  37. int codetagcnt;
  38. int gone;
  39.  
  40. weregone(really)
  41. int really;
  42. {
  43. if (!really && 2*ec+wc<=40) {
  44.   return;
  45.   }
  46. if (ec+wc>0) printf("*******************************************************************************\n");
  47. if (!really) {
  48.   printf("%s: Too many errors/warnings.\n",fontfilename);
  49.   }
  50. printf("%s: Errors: %d, Warnings: %d\n",fontfilename,ec,wc);
  51. if (currline>1) {
  52.   printf("%s: maxlen: %d, actual max line length: %d\n",
  53.     fontfilename,maxlen,maxlinelength);
  54.   if (codetagcnt>0) {
  55.     printf("%s: Code-tagged characters: %d\n",fontfilename,codetagcnt);
  56.     }
  57.   }
  58. printf("-------------------------------------------------------------------------------\n");
  59. gone=1;
  60. }
  61.  
  62. char *my_alloc(size)
  63. int size;
  64. {
  65. char *ptr;
  66.  
  67. ptr=(char *)malloc(size);
  68. if (ptr==NULL) {
  69.   fprintf(stderr,"%s: Out of memory\n",myname);
  70.   }
  71. else {
  72.   return(ptr);
  73.   }
  74. }
  75.  
  76.  
  77. usageerr()
  78. {
  79. fprintf(stderr,"chkfont by Glenn Chappell <ggc@uiuc.edu>\n");
  80. fprintf(stderr,"Version: %s, date: %s\n",VERSION,DATE);
  81. fprintf(stderr,"Checks figlet 2.0/2.1 font files for format errors.\n");
  82. fprintf(stderr,"(Does not modify font files.)\n");
  83. fprintf(stderr,"Usage: %s fontfile ...\n",myname);
  84. exit(1);
  85. }
  86.  
  87.  
  88. readchar()
  89. {
  90. int i,expected_width,k,len,newlen,diff,l;
  91. char endmark,expected_endmark;
  92. int leadblanks,minleadblanks,trailblanks,mintrailblanks;
  93.  
  94. for (i=0;i<charheight;i++) {
  95.   fgets(fileline,maxlen+1000,fontfile);
  96.   if (feof(fontfile)) {
  97.     printf("%s: ERROR (fatal)- Unexpected end of file after line %d.\n",
  98.       fontfilename,currline);
  99.     ec++;
  100.     weregone(1); if (gone) return;
  101.     }
  102.   currline++;
  103.   len=strlen(fileline)-1;
  104.   if (len>maxlinelength) {
  105.     maxlinelength=len;
  106.     }
  107.   if (len>maxlen) {
  108.     printf("%s: ERROR- Line length > maxlen in line %d.\n",
  109.       fontfilename,currline);
  110.     ec++;
  111.     weregone(0); if (gone) return;
  112.     }
  113.   k=len;
  114.   endmark=k<0?'\0':(k==0||fileline[k]!='\n')?fileline[k]:fileline[k-1];
  115.   for(;k>=0?(fileline[k]=='\n' || fileline[k]==endmark):0;k--) {
  116.     fileline[k]='\0';
  117.     }
  118.   newlen=strlen(fileline);
  119.   for (l=0;l<newlen ? fileline[l]==' ' : 0;l++) ;
  120.   leadblanks = l;
  121.   for (l=newlen-1;l>=0 ? fileline[l]==' ' : 0;l--) ;
  122.   trailblanks = newlen-1-l;
  123.   if (i==0) {
  124.     expected_endmark = endmark;
  125.     expected_width = newlen;
  126.     minleadblanks = leadblanks;
  127.     mintrailblanks = trailblanks;
  128.     if (endmark==' ') {
  129.       printf("%s: Warning- Blank endmark in line %d.\n",
  130.         fontfilename,currline);
  131.       wc++;
  132.       weregone(0); if (gone) return;
  133.       }
  134.     }
  135.   else {
  136.     if (leadblanks<minleadblanks) minleadblanks = leadblanks;
  137.     if (trailblanks<mintrailblanks) mintrailblanks = trailblanks;
  138.     if (endmark!=expected_endmark && !incon_endmarkwarn) {
  139.       printf("%s: Warning- Inconsistent endmark in line %d.\n",
  140.         fontfilename,currline);
  141.       printf("%s:          (Above warning will only be printed once.)\n",
  142.         fontfilename);
  143.       incon_endmarkwarn = 1;
  144.       wc++;
  145.       weregone(0); if (gone) return;
  146.       }
  147.     if (newlen!=expected_width) {
  148.       printf("%s: ERROR- Inconsistent character width in line %d.\n",
  149.         fontfilename,currline);
  150.       ec++;
  151.       weregone(0); if (gone) return;
  152.       }
  153.     }
  154.   diff=len-newlen;
  155.   if (diff>2) {
  156.     printf("%s: ERROR- Too many endmarks in line %d.\n",
  157.       fontfilename,currline);
  158.     ec++;
  159.     weregone(0); if (gone) return;
  160.     }
  161.   else if (charheight>1 && (diff!=(i==charheight-1)+1)) {
  162.     if (!endmark_countwarn) {
  163.       printf("%s: Warning- Endchar count convention violated in line %d.\n",
  164.         fontfilename,currline);
  165.       printf("%s:          (Above warning will only be printed once.)\n",
  166.         fontfilename);
  167.       endmark_countwarn = 1;
  168.       wc++;
  169.       weregone(0); if (gone) return;
  170.       }
  171.     }
  172.   }
  173. #ifdef CHECKBLANKS
  174. if (minleadblanks+mintrailblanks>0 && smushmode>=0) {
  175.   printf("%s: Warning- Leading/trailing blanks in char. ending at line %d.\n",
  176.     fontfilename,currline);
  177.   printf("%s:          (Above warning only given when smushmode > -1.)\n",
  178.     fontfilename);
  179.   wc++;
  180.   weregone(0); if (gone) return;
  181.   }
  182. #endif /* #ifdef CHECKBLANKS */
  183. }
  184.  
  185.  
  186. checkit()
  187. {
  188. int i,k,cmtcount,numsread,ffrighttoleft;
  189. char magicnum[5],cha;
  190. long oldord,theord;
  191. int tmpcnt,len;
  192.  
  193. ec=0;wc=0;
  194. incon_endmarkwarn=0; endmark_countwarn=0; nonincrwarn=0;
  195. bigcodetagwarn=0; smallcodetagwarn=0;
  196. deutschcodetagwarn=0; asciicodetagwarn=0;
  197. codetagcnt=0;
  198. gone=0;
  199. if (!strcmp(fontfilename,"-")) {
  200.   fontfilename="(stdin)";
  201.   fontfile=stdin;
  202.   }
  203. else {
  204.   fontfile=fopen(fontfilename,"r");
  205.   if (fontfile == NULL) {
  206.     fprintf(stderr,"%s: Could not open file '%s'\n",myname,fontfilename);
  207.     exit(1);
  208.     }
  209.   }
  210.  
  211. if (fontfile!=stdin) {
  212.   if (strlen(fontfilename)<strlen(FONTFILESUFFIX)?1
  213.     :strcmp(fontfilename+strlen(fontfilename)-4,FONTFILESUFFIX)) {
  214.     printf("%s: ERROR- Filename does not end with '%s'.\n",
  215.       fontfilename,FONTFILESUFFIX);
  216.     ec++;
  217.     weregone(0); if (gone) return;
  218.     }
  219.   }
  220. fscanf(fontfile,"%4s",magicnum);
  221. if (strcmp(magicnum,FONTFILEMAGICNUMBER)) {
  222.   printf("%s: ERROR- Incorrect magic number.\n",fontfilename);
  223.   ec++;
  224.   weregone(0); if (gone) return;
  225.   }
  226. cha=getc(fontfile);
  227. if (cha!='a') {
  228.   printf("%s: Warning- Sub-version character is not 'a'.\n",fontfilename);
  229.   wc++;
  230.   weregone(0); if (gone) return;
  231.   }
  232. fileline=(char*)my_alloc(sizeof(char)*(1001));
  233. if (fgets(fileline,1001,fontfile)==NULL) {
  234.   fileline[0] = '\0';
  235.   }
  236. if (strlen(fileline)>0 ? fileline[strlen(fileline)-1]!='\n' : 0) {
  237.   while(k=getc(fontfile),k!='\n'&&k!=EOF) ; /* Advance to end of line */
  238.   }
  239. numsread=sscanf(fileline,"%c %d %d %d %d %d%*[ ]%d",
  240.   &hardblank,&charheight,&upheight,&maxlen,&smushmode,&cmtcount,
  241.   &ffrighttoleft);
  242. free(fileline);
  243. if (numsread<7) {
  244.   ffrighttoleft=0;
  245.   }
  246. if (6>numsread) {
  247.   printf("%s: ERROR (fatal)- First line improperly formatted.\n",fontfilename);
  248.   ec++;
  249.   weregone(1); if (gone) return;
  250.   }
  251. if (!strchr(posshardblanks,hardblank)) {
  252.   printf("%s: Warning- Unusual hardblank.\n",fontfilename);
  253.   wc++;
  254.   weregone(0); if (gone) return;
  255.   }
  256. if (charheight<1) {
  257.   printf("%s: ERROR (fatal)- charheight not positive.\n",fontfilename);
  258.   ec++;
  259.   weregone(1); if (gone) return;
  260.   }
  261. if (upheight>charheight || upheight<1) {
  262.   printf("%s: ERROR- up_height out of bounds.\n",fontfilename);
  263.   ec++;
  264.   weregone(0); if (gone) return;
  265.   }
  266. if (maxlen<1) {
  267.   printf("%s: ERROR (fatal)- maxlen not positive.\n",fontfilename);
  268.   ec++;
  269.   weregone(1); if (gone) return;
  270.   }
  271. if (smushmode<-1) {
  272.   printf("%s: ERROR- smushmode < -1.\n",fontfilename);
  273.   ec++;
  274.   weregone(0); if (gone) return;
  275.   }
  276. if (smushmode>63) {
  277.   printf("%s: Warning- smushmode > 63.\n",fontfilename);
  278.   wc++;
  279.   weregone(0); if (gone) return;
  280.   }
  281. if (cmtcount<0) {
  282.   printf("%s: ERROR- cmt_count is negative.\n",fontfilename);
  283.   ec++;
  284.   weregone(0); if (gone) return;
  285.   }
  286. if (ffrighttoleft<0 || ffrighttoleft>1) {
  287.   printf("%s: ERROR- rtol out of bounds.\n",fontfilename);
  288.   ec++;
  289.   weregone(0); if (gone) return;
  290.   }
  291.  
  292. for (i=1;i<=cmtcount;i++) {
  293.   while(k=getc(fontfile),k!='\n'&&k!=EOF) ; /* Advance to end of line */
  294.   }
  295.  
  296. maxlinelength = 0;
  297. currline=cmtcount+1;
  298. fileline=(char*)my_alloc(sizeof(char)*(maxlen+1001));
  299. for (i=0;i<102;i++) {
  300.   readchar();
  301.   if (gone) return;
  302.   }
  303.  
  304. oldord=0;
  305. while(fgets(fileline,maxlen+1000,fontfile)!=NULL) {
  306.   currline++;
  307.   len=strlen(fileline)-1;
  308.   if (len>maxlinelength) {
  309.     maxlinelength=len;
  310.     }
  311.   if (len>maxlen) {
  312.     printf("%s: ERROR- Line length > maxlen in line %d.\n",
  313.       fontfilename,currline);
  314.     ec++;
  315.     weregone(0); if (gone) return;
  316.     }
  317.   tmpcnt=sscanf(fileline,"%li",&theord);
  318.   if (tmpcnt<1) {
  319.     printf("%s: Warning- Extra chars after font in line %d.\n",
  320.       fontfilename,currline);
  321.     wc++;
  322.     weregone(0); if (gone) return;
  323.     break;
  324.     }
  325.   codetagcnt++;
  326.   if (theord>65535 && !bigcodetagwarn) {
  327.     printf("%s: Warning- Code tag > 65535 in line %d.\n",
  328.       fontfilename,currline);
  329.     printf("%s:          (Above warning will only be printed once.)\n",
  330.       fontfilename);
  331.     bigcodetagwarn = 1;
  332.     wc++;
  333.     weregone(0); if (gone) return;
  334.     }
  335.   if (theord<-255 && !smallcodetagwarn) {
  336.     printf("%s: Warning- Code tag < -255 in line %d.\n",
  337.       fontfilename,currline);
  338.     printf("%s:          (Above warning will only be printed once.)\n",
  339.       fontfilename);
  340.     smallcodetagwarn = 1;
  341.     wc++;
  342.     weregone(0); if (gone) return;
  343.     }
  344.   if (theord<= -249 && theord>= -255 && !deutschcodetagwarn) {
  345.     printf("%s: Warning- Code tag in \"Deutsch\" range in line %d.\n",
  346.       fontfilename,currline);
  347.     printf("%s:          (Above warning will only be printed once.)\n",
  348.       fontfilename);
  349.     deutschcodetagwarn = 1;
  350.     wc++;
  351.     weregone(0); if (gone) return;
  352.     }
  353.   if (theord<127 && theord>0 && !asciicodetagwarn) {
  354.     printf("%s: Warning- Code tag in ASCII range in line %d.\n",
  355.       fontfilename,currline);
  356.     printf("%s:          (Above warning will only be printed once.)\n",
  357.       fontfilename);
  358.     asciicodetagwarn = 1;
  359.     wc++;
  360.     weregone(0); if (gone) return;
  361.     }
  362.   else if (theord<=oldord && theord!=0 && oldord!=0 && !nonincrwarn) {
  363.     printf("%s: Warning- Non-increasing code tag in line %d.\n",
  364.       fontfilename,currline);
  365.     printf("%s:          (Above warning will only be printed once.)\n",
  366.       fontfilename);
  367.     nonincrwarn = 1;
  368.     wc++;
  369.     weregone(0); if (gone) return;
  370.     }
  371.   oldord=theord;
  372.   readchar();
  373.   if (gone) return;
  374.   }
  375.  
  376. if (fontfile!=stdin) fclose(fontfile);
  377.  
  378. weregone(1); if (gone) return;
  379. }
  380.  
  381.  
  382. int main(argc,argv)
  383. int argc;
  384. char *argv[];
  385. {
  386. int arg;
  387.  
  388. if ((myname=strrchr(argv[0],'/'))!=NULL) {
  389.   myname++;
  390.   }
  391. else {
  392.   myname = argv[0];
  393.   }
  394. if (argc<2) {
  395.   usageerr();
  396.   }
  397. for (arg=1;arg<argc;arg++) {
  398.   fontfilename=argv[arg];
  399.   fileline=NULL;
  400.   checkit();
  401.   if (fileline!=NULL) free(fileline);
  402.   }
  403. exit(0);
  404. }
  405.